#ifndef ROHost_H
#define ROHost_H

#include <QObject>
#include <QQmlComponent>
#include <QVariant>
#include <QVariantMap>
#include <QList>
#include <ROPlayerValidator.h>
#include "ROPlayer.h"

//共享对象系统的服务端

class ROPlayer;
class ROComponent;
class ROHostPrivate;
class QQuickROChannel;
class ROSyncProperty;
class RORPC;
class ROHelper;
class ROSyncCreation;
class ROHost:public QObject
{
    Q_OBJECT
    QML_ELEMENT
    Q_PROPERTY(bool active READ active WRITE setActive NOTIFY activeChanged FINAL)
    Q_PROPERTY(int port READ port WRITE setPort NOTIFY portChanged FINAL)
    Q_PROPERTY(QQmlComponent *playerDelegate READ playerDelegate WRITE setPlayerDelegate NOTIFY playerDelegateChanged FINAL)
    Q_PROPERTY(QList<ROPlayer *> players READ players WRITE setPlayers NOTIFY playersChanged FINAL)
public:
    enum Policy
    {
        Server,//以独立服务器的方式启动，开启网络端口但不创建自身Player
        ListenServer,//以监听服务器的方式启动，自身既是客户端又是服务器，开启网络端口并创建一个属于自身的Player
        Offline//以单机模式启动，创建自身Player但不开启网络端口
    };
    Q_ENUM(Policy)

    ROHost();
    ~ROHost();


    bool active() const;
    void setActive(bool newActive);

    int port() const;
    void setPort(int newPort);

    QQmlComponent *playerDelegate() const;
    void setPlayerDelegate(QQmlComponent *newPlayerDelegate);

    QList<ROPlayer *> players() const;
    void setPlayers(const QList<ROPlayer *> &newPlayers);

    QVariantMap hostPlayerParam() const;
    void setHostPlayerParam(const QVariantMap &newHostPlayerParam);

    Policy policy() const;
    void setPolicy(Policy newPolicy);

    QQmlComponent *rootComponent() const;
    void setRootComponent(QQmlComponent *newRootComponent);

    QObject *rootObject() const;
    void setRootObject(QObject *newRootObject);

    ROPlayerValidator *playerValidator() const;
    void setPlayerValidator(ROPlayerValidator *newPlayerValidator);

signals:
    void activeChanged();

    void portChanged();

    void playerDelegateChanged();

    void playersChanged();

    void newPlayer(ROPlayer* player);//有新的玩家加入了

    void hostPlayerParamChanged();

    void policyChanged();

    void rootComponentChanged();

    void rootObjectChanged();

    void playerValidatorChanged();

private:
    void registerObject(QObject* obj,QStringList reason);
    void unRegisterObject(QObject* obj);
    void validate();
    void startUp();
    void cleanUp();
    void broadcastRPC(int objId,QString name,const QVariantList& param,const QList<ROPlayer*>& playerIds,bool safe);
    void handleRPC(const QVariantMap& v);

    void onNewConnection(QQuickROChannel* con);
    void onNewMessage(QQuickROChannel* con,QString topic,QVariant value);
    void sendInitializeMessage(QQuickROChannel* con);
    void createPlayer(int id,QQuickROChannel* con,const QVariantMap& param);
    void onPropertyUpdate(ROSyncProperty* obj,const QStringList& prop,bool safe);
    void onLogin(QQuickROChannel *con,const QVariantMap& value);
    void onPlayerRemoved(ROPlayer* player);
    void createHostPlayer();
    void kickPlayer(ROPlayer* player,QString reason);

private:
    Policy m_policy = Server;//服务器运行模式
    bool m_active = false;//是否启动
    int m_port = 0;//启动端口号
    QQmlComponent* m_rootComponent = nullptr;//根同步对象的组件
    QObject* m_rootObject = nullptr;//根对象
    QQmlComponent* m_playerDelegate = nullptr;//Player的生成器
    QList<ROPlayer*> m_players;//已连接到服务端的客户端
    ROHostPrivate* _P = nullptr;//后台
    QVariantMap m_hostPlayerParam;//当以监听服务器启动时，房主的player的初始属性
    ROPlayerValidator* m_playerValidator = nullptr;//玩家加入的过滤器
    friend class ROComponent;
    friend class ROSyncProperty;
    friend class RORPC;
    friend class ROSyncCreation;
    friend class ROHelper;
    friend class ROPlayer;
    Q_PROPERTY(QVariantMap hostPlayerParam READ hostPlayerParam WRITE setHostPlayerParam NOTIFY hostPlayerParamChanged FINAL)
    Q_PROPERTY(Policy policy READ policy WRITE setPolicy NOTIFY policyChanged FINAL)
    Q_PROPERTY(QQmlComponent *rootComponent READ rootComponent WRITE setRootComponent NOTIFY rootComponentChanged FINAL)
    Q_PROPERTY(QObject *rootObject READ rootObject WRITE setRootObject NOTIFY rootObjectChanged FINAL)
    Q_PROPERTY(ROPlayerValidator *playerValidator READ playerValidator WRITE setPlayerValidator NOTIFY playerValidatorChanged FINAL)
};

#endif
